#include <png.h>
#include <string>
#include <array>
#include <vector>
#include "util.h"

namespace ux_png {

struct Pixel {
  std::array<unsigned char, 4> _{};
  int color_type_{PNG_COLOR_TYPE_RGBA};
  // RGBA
  // GA
  void set(unsigned char v, const size_t & idx) { _[idx] = v; }
  unsigned char get(const size_t & idx) const { return _[idx]; }
  bool operator==(const Pixel& other) const {
    if (color_type_ != other.color_type_) return false;
    auto l = ColorType2Channels(color_type_);
    for (int i = 0; i < l; i++) {
      if (_[i] != other.get(i)) return false;
    }
    return true;
  }
  Pixel ToGray();
};

class PngData {
public:
  PngData() = default;

  void InitInfoObject(
          int channels,
          int color_type,
          int bit_depth);

  int Channels() const;
  int ColorType() const;
  int Width() const;
  int Height() const;
  int BitDepth() const;
  int HaveAlpha() const;

  // operator

  // put `other` to the left of this PngData
  int LeftPut(const PngData& other);

  // change this pngData from rgb -> gray
  int Rgb2Gray();

  // this operator will change color_type and channels
  void SetColorType(int new_color_type);
  ~PngData();

  std::vector<std::vector<Pixel>> mp_;

private:

  // info object
  int channels_{};
  int color_type_{};
  int bit_depth_{};

  // 是否存在透明通道
  bool have_alpha_{};

};

int ReadPngDataFromImgFile(const char * img_name, PngData* png_data);

int ReadAndCheckPNGFromImgFile(const char * img_name, PngData* png_data);

int WritePngDataToImgFile(const char * img_name, const PngData* pngData);

}